package com.panopset.gui.container;

import static com.panopset.Util.dspmsg;
import static com.panopset.Util.getCanonicalPath;
import static com.panopset.Util.x;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.Vector;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

import com.panopset.centralen.util.MathUtil;
import com.panopset.gui.TButton;
import com.panopset.gui.TPanel;

/**
 * Super class of PanFile and PanDirectory.
 *
 * @author Karl Dinwiddie
 *
 */
public abstract class AbstractPanFile extends PanField<JPanel> {
    /**
    *
    * @param borderTitle
    *            Border title.
    * @param toolTipText
    *            Tool tip text.
    */
   public AbstractPanFile(final String borderTitle, final String toolTipText) {
       this(borderTitle, toolTipText, "");
   }

   /**
    *
    * @param borderTitle
    *            Border title.
    * @param toolTipText
    *            Tool tip text.
    * @param defaultValue
    *            Default value.
    */
   public AbstractPanFile(final String borderTitle, final String toolTipText,
           final String defaultValue) {
       super(borderTitle, toolTipText, defaultValue);
       getPanel().setLayout(new GridLayout(1, 1));
   }

   /**
    * Description.
    */
   private String description = "";

   /**
    * Update listeners.
    */
   private final Vector<UpdateListener> updateListeners
       = new Vector<UpdateListener>();

   /**
    * Add update listener.
    *
    * @param updateListener
    *            Update listener.
    */
   public final void addUpdateListener(final UpdateListener updateListener) {
       updateListeners.add(updateListener);
   }

   /**
    *
    */
   private void update() {
       for (UpdateListener updateListener : updateListeners) {
           updateListener.update();
       }
   }

   @Override
   public final String getComponentValue() {
       return getFileTextField().getText();
   }

   @Override
   public final void setComponentValue(final String value) {
       getFileTextField().setText(value);
       update();
   }

   /**
    * Set selected file.
    *
    * @param file
    *            Selected file.
    */
   public final void setSelectedFile(final File file) {
       if (file != null && file.exists()) {
           getFileTextField().setText(getCanonicalPath(file));
           update();
       }
   }

   /**
    * Get file.
    *
    * @return File.
    */
   public final File getFile() {
       String path = getFileTextField().getText();
       if (path == null) {
           return null;
       }
       if (path.trim().length() == 0) {
           return null;
       }
       return new File(path);
   }

   /**
    * Browse for file.
    */
   final void doBrowse() {
       setSelectedFile(fileDialog(JFileChooser.OPEN_DIALOG));
   }

   /**
    * Create a file or directory path.
    */
   protected abstract void create();

   /**
    * Create new file.
    */
   final void doNew() {
       setSelectedFile(fileDialog(JFileChooser.SAVE_DIALOG));
       File f = getFile();
       if (f == null || "".equals(getCanonicalPath(f))) {
           dspmsg(x("No file selected."));
           return;
       }
       create();
   }

   /**
    * @param dialogType
    *            JFileChooser Dialog type.
    * @return Selected file.
    */
   private File fileDialog(final int dialogType) {
       File rtn = null;
       File dftPath = new File(getCanonicalPath(new File("x")))
               .getParentFile();
       JFileChooser chooser = new JFileChooser();
       if ("".equals(getFileTextField().getText().trim())) {
           if ((dftPath != null) && (getCanonicalPath(dftPath).length() > 0)) {
               chooser.setSelectedFile(dftPath);
           }
       } else {
           chooser.setSelectedFile(getFile());
       }
       chooser.setFileSelectionMode(getFileSelectionMode());
       chooser.setDialogTitle(getPrompt());
       chooser.setDialogType(dialogType);
       if (chooser.showOpenDialog(new JFrame())
               == JFileChooser.APPROVE_OPTION) {
           rtn = chooser.getSelectedFile();
       }
       if (rtn != null) {
           getFileTextField().setText(getCanonicalPath(rtn));
       }
       update();
       return rtn;
   }

   /**
    * @return JFileDialog selection mode.
    */
   protected abstract int getFileSelectionMode();

   /**
    * @return PanFile panel.
    */
   public final JPanel createGui() {
       return getPanel();
   }

   /**
    * Create component.
    */
   private TPanel panel;

   @Override
   public final TPanel createComponent() {
       String requiredPrompt = null;

       requiredPrompt = createPrompter() + " " + x("required");

       panel = new TPanel.Builder().tip(
               x("Select") + " " + description).layout(
               new GridBagLayout()).requiredPrompt(requiredPrompt).construct();

       GridBagConstraints gbc = null;

       TButton btn = new TButton(x("New"), KeyEvent.VK_N, x("Create new")
               + " " + description, new ActionListener() {

           public void actionPerformed(final ActionEvent e) {
               doNew();
           }
       });
       gbc = new GridBagConstraints();
       gbc.gridx = 0;
       gbc.gridy = 0;
       gbc.weightx = 0;
       panel.add(btn, gbc);
       btn = new TButton(x("Browse"), KeyEvent.VK_B, x("Browse for")
               + " " + description, new ActionListener() {
           @Override
           public void actionPerformed(final ActionEvent e) {
               doBrowse();
           }
       });
       gbc = new GridBagConstraints();
       gbc.gridx = 1;
       gbc.gridy = 0;
       gbc.weightx = 0;
       panel.add(btn, gbc);
       gbc = new GridBagConstraints();
       gbc.gridx = 2;
       gbc.gridy = 0;
       gbc.fill = GridBagConstraints.HORIZONTAL;
       gbc.weightx = 1.0;

       panel.add(getFileTextField(), gbc);
       return panel;
   }

   /**
    * File text field.
    */
   private JTextField fileTextField;

   /**
    * @return File text field.
    */
   private JTextField getFileTextField() {
       if (fileTextField == null) {
           fileTextField = new JTextField(MathUtil.TEN);
       }
       return fileTextField;
   }

   /**
    * Prompt.
    */
   private String prompt;

   /**
    * @return Prompt.
    */
   private String getPrompt() {
       if (prompt == null) {
           prompt = x("Please select a") + " " + createPrompter();
       }
       return prompt;
   }

   /**
    * @return directory or file prompter.
    */
   protected abstract String createPrompter();
}
